<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <h4>typeof</h4>
    <ol>
        <li>typeof null "object" 对象存储在计算机作用都是以000开头, null也是，所以typeof检测出来的结果是对象</li>
        <li>普通对象 / 数组对象 / 日期对象 / 正则对象 / 都是object</li>
    </ol>
    <h4>instanceof 检测当前实例是否属于这个类</h4>
    <ol>
        <li>底层机制: 只要当前类出现在实例的原型链上结果都是true</li>
        <li>由于我们可以肆意的修改原型的指向, 所以检测出来的结果是不准的</li>
        <li>不能检测基础数据类型</li>

    </ol>
    <h4>construct</h4>
    <ol>
        <li>看起来比instanceof好用一些</li>
        <li>constructor是可以随便改的，改过之后就错了</li>
    </ol>
    <h4>Object.prototype.toString.call([value])</h4>
    <ol>
        <li>标准检测数据类型的办法,Object.prototype.toString不是转换成字符串返回当前实例</li>
        <li>推测: 是不是只要把object.prototype.toString执行,让里面的this指向当前的实例</li>
    </ol>

    <h3>总结:</h3>
    <h4>简单数据类型使用typeof</h4>
    <h4>复杂数据类型使用Object.prototype.toString.call</h4>

</body>
<script>
    // 数据类型检测4种
    // typeof
    // --- typeof null "object" 对象存储在计算机作用都是以000开头, null也是，所以typeof检测出来的结果是对象
    // --- 普通对象 / 数组对象 / 日期对象 / 正则对象 / 都是object
    console.log("typeof string", typeof "string")
    console.log("typeof ''", typeof "")
    console.log("typeof 126", typeof 126)
    console.log("typeof null", typeof null)
    console.log("typeof undefined", typeof undefined)
    console.log("typeof ['string', 1, 'mortal']", typeof ["string", 1, "mortal"])
    console.log("typeof /123$/", typeof /123$/)
    console.log("typeof new Date()", typeof new Date())

    // instanceof 检测当前实例是否属于这个类
    // 底层机制: 只要当前类出现在实例的原型链上结果都是true
    // 由于我们可以肆意的修改原型的指向, 所以检测出来的结果是不准的
    // 不能检测基础数据类型
    let arr = [];
    console.log(arr, "arr instanceof Array", arr instanceof Array);
    console.log(arr, "arr instanceof RegExp", arr instanceof RegExp);
    console.log(arr, "arr instanceof Object", arr instanceof Object);

    function fn() {
        this.x = 100
    }
    fn.prototype = Object.create(Array.prototype);
    let f = new fn();
    console.log(f, f instanceof Array)

    console.log("1 instanceof number", 1 instanceof Number);
    console.log("'mortal' instanceof String", "mortal" instanceof String);

    function instance_of(example, classFunc) {
        let classFuncPrototype = classFunc.prototype;
        let proto = Object.getPrototypeOf(example);
        while (true) {
            if (proto === null) {
                return false
            }
            if (proto === classFuncPrototype) {
                return true
            }
            proto = Object.getPrototypeOf(proto)
        }
    }
    console.log(arr, "arr instanceof Array", instance_of(arr, Array));
    console.log(arr, "arr instanceof RegExp", instance_of(arr, RegExp));
    console.log(arr, "arr instanceof Object", instance_of(arr, Object));

    // construct
    // -------看起来比instanceof好用一些
    // -------construct可以改
    console.log(arr, "arr constructor === Array", arr.constructor === Array);   //true
    console.log(arr, "arr constructor === RegExp", arr.constructor === RegExp);//false
    console.log(arr, "arr constructor === Object", arr.constructor === Object);//false

    // constructor是可以随便改的，改过之后就错了
    Number.prototype.constructor = "AA"
    let n = 1;
    console.log(n, "n constructor === Number", n.constructor === Number); //true

    // Object.prototype.toString.call([value])
    // 标准检测数据类型的办法,Object.prototype.toString不是转换成字符串返回当前实例
    let obj = {
        name: "mortal"
    }
    console.log(obj.toString());  // [object Object]
    // 推测: 是不是只要把object.prototype.toString执行,让里面的this指向当前的实例
    console.log("Object.prototype.tostring.call(1)", Object.prototype.toString.call(1))
    console.log("Object.prototype.tostring.call(NaN)", Object.prototype.toString.call(NaN))
    console.log("Object.prototype.tostring.call('')", Object.prototype.toString.call(""))
    console.log("Object.prototype.tostring.call(true)", Object.prototype.toString.call(true))
    console.log("Object.prototype.tostring.call(symbol('xx'))", Object.prototype.toString.call(Symbol("mortal")))
    console.log("Object.prototype.tostring.call({})", Object.prototype.toString.call(obj))
    console.log("Object.prototype.tostring.call([])", Object.prototype.toString.call([1, 2, 3]))
    console.log("Object.prototype.tostring.call(/^$/)", Object.prototype.toString.call(/^$/))
    console.log("Object.prototype.tostring.call(function(){})", Object.prototype.toString.call(function () { }))
    console.log("Object.prototype.tostring.call(null)", Object.prototype.toString.call(null))
    console.log("Object.prototype.tostring.call(new Date())", Object.prototype.toString.call(new Date()))
    console.log("Object.prototype.tostring.call(undefined)", Object.prototype.toString.call(undefined))

</script>

</html>